/****************************************************************************
 * Copyright 2009 Huascar A. Sanchez                                        *
 *                                                                          *
 * Licensed under the Apache License, Version 2.0 (the "License");          *
 * you may not use this file except in compliance with the License.         *
 * You may obtain a copy of the License at                                  *
 *                                                                          *
 *     http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                          *
 * Unless required by applicable law or agreed to in writing, software      *
 * distributed under the License is distributed on an "AS IS" BASIS,        *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 * See the License for the specific language governing permissions and      *
 * limitations under the License.                                           *
 ****************************************************************************/
package com.gotobject.filter;

import static com.gotobject.filter.FilterQ.from;
import static com.gotobject.filter.common.Aggregations.*;
import static com.gotobject.filter.common.Predicates.*;
import static com.gotobject.filter.common.Iterables.asList;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

/**
 * @author huascar.sanchez@gmail.com (Huascar A. Sanchez)
 */
public class PartitionResultTest {
    @Test
    public void partitionOperator_TakeWhile_General() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        for(Integer each : from(numbers).select((mod(2)))){
            assertSame("should be multiple of 2", 0, (each % 2));
        }

    }


    @Test
    public void partitionOperator_TakeWhile_Between() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        for(Integer each : from(numbers).select((between(45, 60)))){
            assertTrue("should be either 45, 44, 88 or 60", each.equals(44) || each.equals(88) || each.equals(45)|| each.equals(60));
        }

        final List<String> pronouns = Arrays.asList("Me", "You", "We", "They", "It", "She", "He");
        for(String each : from(pronouns).select((between("You", "It")))){
            assertTrue("should be either You, We, They or It", "You".equals(each) || "We".equals(each) || "They".equals(each) || "It".equals(each));
        }
    }

    @Test
    public void partitionOperator_TakeWhile_Negated() throws Exception {
        final List<String> names = Arrays.asList("Robert", "Roberta");
        for(String each : from(names).select((not(endsWith("ta"))))){
            assertSame("the answer is Robert", "Robert", each);
        }
    }


    @Test
    public void partitionOperator_SkipWhile() throws Exception {
        // will skip elements that are multiple of 2
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 880, 6, 12, 8);
        for(Integer each : from(numbers).skip((mod(2)))){
            assertSame("should not be multiple of 2", 1, (each % 2));
        }
    }

    @Test
    public void partitionOperator_SkipWhile_CompoundCondition() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 880, 6, 12, 8);
        final Iterable<Integer> r = from(numbers).skip(mod(2).or(eq(67)));
        for(Integer each : r){
            assertSame("should not be multiple of 2", 1, (each % 2));
        }
    }


    @Test
    public void partitionOperator_Take_General() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        final Iterable<Integer> result =  from(numbers).select(3);
        for(Integer each : result){
            assertTrue("should be either 1, 3, 67", each.equals(1) || each.equals(3) || each.equals(67));
        }

        for(Integer each: from(Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8)).select(1)){
            assertSame("equals to 1", 1, each);
        }
    }

    @Test
    public void partitionOperator_Take_Max() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        assertSame("67 should be the max number", 67, max(from(numbers).select(3)));
    }

    @Test
    public void partitionOperator_Take_Min() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        assertSame("1 should be the min number", 1, min(from(numbers).select(3)));

    }

    @Test
    public void partitionOperator_Skip() throws Exception {
        final List<Integer> numbers = Arrays.asList(1, 3, 67, 45, 44, 88, 60, 12, 8);
        final Iterable<Integer> results = from(numbers).skip(3);
        for(Integer each : results){
            assertTrue("should be either 45, 44, 88, 60, 12, 8", each.equals(45) || each.equals(44)
                    || each.equals(88) || each.equals(60)
                    || each.equals(12) || each.equals(8)
            );
        }

        assertSame("88 should be the max number", 88, max(results));
        assertSame("8 should be the min number", 8, min(results));
    }

    @Test
    public void partitionOperator_Skip_Negated() throws Exception {
        final List<String> names = Arrays.asList("Robert", "Roberta", "Charlie", "Kent", "Paolo", "Mandini", "Salomon", "Matt");
        final List<String> result = asList(from(names).skip(not(endsWith("a", "e", "o"))));
        assertSame("the answer is 3 elements", 3, result.size());
    }

    @Test
    public void partitionOperator_Count() throws Exception {
        final List<String> names = Arrays.asList("Robert", "Roberta", "Charlie", "Kent", "Paolo", "Mandini", "Salomon", "Matt");
        assertSame("the answer is 8 elements", 8, count(from(names).select()));

    }
}
